package com.dy.security.config;

import com.dy.security.session.MyInvalidSessionStrategy;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.session.HttpSessionEventPublisher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: ding-yu
 * @Date: 2022/5/19 17:24
 * @Desctiption: (描述)
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/api/user/**").hasAnyRole("user")
                .antMatchers("/api/admin/**").hasAnyRole("admin")
                .antMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf()
                .disable()
                //开启会话
                .sessionManagement()
                .sessionFixation()
                //设置会话固定防御策略
                .migrateSession()
                //自定义session过期返回信息
                .invalidSessionStrategy(new MyInvalidSessionStrategy())
                //最大会话并发数，相当于同个用户只能一个会话，多个会话会被挤掉
                .maximumSessions(1)
                //自定义会话销毁后，跳转路径
//                .expiredUrl("/")
                //自定义会话行为
                //禁止后来者不能再使用当前用户登录，必须当前登录主动注销后登录
                .maxSessionsPreventsLogin(true);
    }

    /**
     * 提供HttpSessionEventPublisher实例。Spring security中通过一个Map集合来维护当前的HttpSession记录，进而实现
     * 会话的并发管理。当用户登录成功时，就向集合中添加一条HttpSession记录；当会话销毁时，就从集合中移除一条HttpSession
     * 记录。HttpSessionEventPublisher实现了HttpSessionListener接口，可以监听到HttpSession的创建和销毁事件，并将
     * HttpSession的创建/销毁事件发布出去，这样，当有HttpSession销毁时，spring security就可以感知到该事件了
     */
    @Bean
    HttpSessionEventPublisher httpSessionEvent(){
        return new HttpSessionEventPublisher();
    }
}
